/**
 * FreeZzaphPluginFactory.java
 * 
 * FreeZzaph is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * FreeZzaph is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.
 */
package freezzaph;

import java.io.File;
import java.io.FileFilter;
import java.net.URI;
import java.util.HashMap;


import freezzaph.classloader.PluginClassLoader;
import freezzaph.exceptions.PluginException;
import freezzaph.plugins.FreeZzaphDownloadPlugin;
import freezzaph.plugins.FreeZzaphPlugin;
import freezzaph.plugins.FreeZzaphPluginPreferences;
import freezzaph.plugins.FreeZzaphPostProcessorPlugin;

/**
 * Class for loading plugins.
 * 
 * @author FreeZzaph
 */
final class FreeZzaphPluginFactory {
	
	/**
	 * FileFilter that accepts files that match
	 * *.fzzaph.
	 * 
	 * @author FreeZzaph
	 */
	private final class FZzPluginFilter implements FileFilter {

		/**
		 * I think, therefore I am.
		 */
		public FZzPluginFilter() {/**/}

		/*
		 * (non-Javadoc)
		 * @see java.io.FileFilter#accept(java.io.File)
		 */
		public boolean accept(File pathname) {
			String filename = pathname.getName(); 
			if (filename.length() > 7 && filename.substring(filename.length() - 7, filename.length()).equals(".fzzaph")) {
				return true;
			}
			return false;
		}
	}

	private HashMap<String, FreeZzaphDownloadPlugin> downloadPluginList = new HashMap<String, FreeZzaphDownloadPlugin>();
	private HashMap<String, FreeZzaphPostProcessorPlugin> postProcessorPluginList = new HashMap<String, FreeZzaphPostProcessorPlugin>();
	
	
	public void loadPlugins() throws PluginException {
		
		File pluginFolder = new File("./plugins");
		
		// For any file that matches "*.fzzaph"...
		try {
			for (File pluginFile : pluginFolder.listFiles(new FZzPluginFilter())) {
				try {
					// Load the file's plugins
					URI uri = pluginFile.toURI();
					PluginClassLoader pcl = new PluginClassLoader(uri);
					Class<?>[] pluginClass = pcl.loadPluginClass();
					
					for (Class<?> plugin : pluginClass) {
						if (plugin != null) {
							FreeZzaphPlugin fzp = (FreeZzaphPlugin) plugin.newInstance();
							if (fzp instanceof FreeZzaphDownloadPlugin) {
								FreeZzaphDownloadPlugin fzdp = (FreeZzaphDownloadPlugin) fzp;
								
								String pluginName = fzdp.getPluginName(); 
								if (!downloadPluginList.containsKey(pluginName)) {
									fzdp.provideSettings(new FreeZzaphPluginPreferences(FreeZzaph.prefs.node(pluginName)));
									downloadPluginList.put(pluginName, fzdp);
								} else {
									System.err.printf("Conflicting plugin names, tried loading plugin with name '%s', but one already existed with such a name.\n", pluginName);
								}
							} else if (fzp instanceof FreeZzaphPostProcessorPlugin) {
								FreeZzaphPostProcessorPlugin fzppp = (FreeZzaphPostProcessorPlugin) fzp;
								
								String pluginName = fzppp.getPluginName(); 
								if (!postProcessorPluginList.containsKey(pluginName)) {
									postProcessorPluginList.put(pluginName, fzppp);
								} else {
									System.err.printf("Conflicting plugin names, tried loading plugin with name '%s', but one already existed with such a name.\n", pluginName);
								}
							} else {
								String pluginName = fzp.getPluginName();
								System.err.printf("Tried loading plugin with name '%s', but its type is unknown.\n", pluginName);
							}
						}
					}
					
				} catch (Exception e) {
					System.err.printf("Failed loading plugin from %s\n", pluginFile.getName());
					continue;
				}
			}
		} catch (SecurityException e) {
			throw new PluginException("Cannot access plugin directory\n");
		}
		
	}

	/**
	 * Get all the loaded download plugins
	 * 
	 * @return HashMap containing all the loaded download plugins
	 */
	public HashMap<String, FreeZzaphDownloadPlugin> getDownloadPluginList() {
		return downloadPluginList;
	}
	
	public HashMap<String, FreeZzaphPostProcessorPlugin> getPostProcessorPluginList() {
		return postProcessorPluginList;
	}

}
